Skip to content

HW#8_Khyzhniak#32

Open
dmytro-khyzhniak wants to merge 5 commits intomasterfrom
HW#8_Khyzhniak_2
Open

HW#8_Khyzhniak#32
dmytro-khyzhniak wants to merge 5 commits intomasterfrom
HW#8_Khyzhniak_2

Conversation

@dmytro-khyzhniak
Copy link
Collaborator

HW was rewritten. Now it is written with classes.

TASK: Write a basic TODO list using the MVC pattern.

Requirements
✅ Base UI (you can use a bootstrap.css)

  • TODO units can be
    ✅ add
    ✅ mark as done
    ✅ unmark as done
    ✅ delete

  • Store data in RAM
    ✅ optional improvement - save in local storage

  • Optional improvements:
    ❗️ cover the code with unit tests
    ✅ add filter by completed and no


class View {
constructor() {
this.toDoContainer = document.querySelector('.to-do');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is better to use id if you are processing only one element.

it is also worth considering error handling if the element is not found

Comment on lines 7 to 34
const h1 = document.createElement('h1');
h1.innerText = 'THINGS TO DO ✌️';
document.body.prepend(h1);

this.showButton = document.createElement('button');
this.showButton.classList.add('to-do__button', 'to-do__button--show');
this.showButton.title = 'Show all tasks';
this.showButton.innerText = 'SHOW';
this.toDoContainer.appendChild(this.showButton);

this.input = document.createElement('input');
this.input.classList.add('to-do__input');
this.input.placeholder = 'Add a new task 👈';
this.toDoContainer.appendChild(this.input);

this.addButton = document.createElement('button');
this.addButton.classList.add('to-do__button', 'to-do__button--add');
this.addButton.title = 'Add a new task';
this.addButton.innerText = 'ADD';
this.toDoContainer.appendChild(this.addButton);

this.tasksContainer = document.createElement('div');
this.tasksContainer.classList.add('tasks');
this.toDoContainer.appendChild(this.tasksContainer);

this.tasksList = document.createElement('ul');
this.tasksList.classList.add('tasks__list');
this.tasksContainer.appendChild(this.tasksList);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not the responsibility of the constructor. it should be a separate method

all class names / ids / texts are best used from constants

}

renderTasks(tasks) {
if (tasks.length === 0 && $C.isFiltered() === 'false') {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you take a controller as an unobvious dependency?
the method can only work with input parameters

this.toggleShowButton();
this.showButton.style.display = 'none';
this.tasksList.style.display = 'none';
$C.tasksListIsHidden = true;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we not use the controller as a dependency?

Comment on lines 49 to 53
this.tasksList = document.querySelector('.tasks__list');
this.showButton = document.querySelector('.to-do__button--show');

this.tasksList.style.display = 'inline-block';
this.showButton.style.display = 'inline-block';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for clarity of use, it is better to take keys from the private properties of the class

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite understood. Let`s discuss this tomorrow during the meeting.

Comment on lines 55 to 66
if (this.tasksList.style.height >= '25vh') {
this.tasksList.style.height = '0px';
this.tasksList.style.overflow = 'hidden';
this.tasksList.style.padding = '0px';
this.showButton.innerHTML = 'SHOW';
this.showButton.style.background = '#87ff93';
} else {
this.tasksList.style.height = '25vh';
this.tasksList.style.overflowY = 'scroll';
this.tasksList.style.padding = '15px';
this.showButton.innerHTML = 'CLOSE';
this.showButton.style.background = '#ff8f87';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to smear css on js on such a scale is bad.
can we just change the class on the wrapper? to leave css in css

Comment on lines 72 to 74
<li class="tasks__list-item">
<div class="tasks__title tasks__title--last">CURRENT TASKS</div>
</li>`;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to create this html by code?

this.createTasksListItems(tasks);

let filterButtonText;
if ($C.isFiltered() === 'true') {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we solve this without importing the controller?

class Model {
constructor() {}

addTask(title) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add what task? where? can we write a better name?

}

getTasksList() {
const tasks = JSON.parse(localStorage.getItem('savedTasks')) ?? { list: [] };
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'savedTasks' - better save in private property

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. How exactly should I implement "private"?

Comment on lines 6 to 11
const currentTasks = this.getTasksList();

currentTasks.push({
'title': title,
'isCompleted': false
});
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

smearing logic. why can't all this happen in the setTasksList method?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Function: Adding a new task. Input - title (string)
  2. Function: Saving current tasks list - tasksList(array). For example, after deleting tasks.

Improved function names for a better visible difference.

Comment on lines 6 to 7
this.invalidInputTimer = null;
this.tasksListIsHidden = true;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is better to describe properties explicitly.

}
}

handleClick(e) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle what Click? pls, use more descriptive names.

Comment on lines 17 to 19
$V.addButton.style.backgroundColor = '#87ff93';
} else {
$V.addButton.style.backgroundColor = '#fff';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if possible, it is better to leave the css in the css file

Comment on lines 48 to 55
let isDone = tasks[index].isCompleted;

if (isDone) {
isDone = false;
} else {
isDone = true;
}
tasks[index].isCompleted = isDone;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tasks[index].isCompleted = !tasks[index].isCompleted;

Comment on lines 62 to 65
const tasks = $M.getTasksList();
tasks.splice(index, 1);

$M.setTasksList(tasks);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

business logic about how exactly we delete the task is better placed in the model

Comment on lines 85 to 89
if ($V.input.value.length > 0) {
if ($C.tasksListIsHidden) {
$C.tasksListIsHidden = false;
$V.toggleShowButton();
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to avoid nested ifs

clearTimeout(this.invalidInputTimer);

this.invalidInputTimer = setTimeout(() => {
$V.input.style.border = '1px solid #000';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭

Comment on lines 110 to 114
if (value.length > 0) {
return true;
} else {
return false;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just as a suggestion

return value.length > 0;

}
}

anyTasksAlreadySaved() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls, use verbs for the name of the methods

}

isFiltered() {
return localStorage.getItem('isFiltered') ?? 'false';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why string type?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants